// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com

// ReSharper disable CheckNamespace
// ReSharper disable ClassNeverInstantiated.Global
// ReSharper disable CommentTypo
// ReSharper disable IdentifierTypo
// ReSharper disable InconsistentNaming
// ReSharper disable StringLiteralTypo
// ReSharper disable UnusedParameter.Local

/*
 * Ars Magna project, http://arsmagna.ru
 */

#region Using directives

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Collections;

#endregion

#nullable enable

namespace AM.Reporting.Data
{
    /// <summary>
    /// Represents a datasource based on <b>DataView</b> class.
    /// </summary>
    /// <remarks>
    /// This class is used to support AM.Reporting.Net infrastructure, do not use it directly.
    /// If you want to use data from <b>DataView</b> object, call the
    /// <see cref="AM.Reporting.Report.RegisterData(DataView, string)"/> method of the <b>Report</b>.
    /// </remarks>
    public class ViewDataSource : DataSourceBase
    {
        #region Properties

        /// <summary>
        /// Gets the underlying <b>DataView</b> object.
        /// </summary>
        public DataView View => Reference as DataView;

        #endregion

        #region Private Methods

        private Column CreateColumn (DataColumn column)
        {
            var c = new Column();
            c.Name = column.ColumnName;
            c.Alias = column.Caption;
            c.DataType = column.DataType;
            if (c.DataType == typeof (byte[]))
            {
                c.BindableControl = ColumnBindableControl.Picture;
            }
            else if (c.DataType == typeof (bool))
            {
                c.BindableControl = ColumnBindableControl.CheckBox;
            }

            return c;
        }

        private void CreateColumns()
        {
            Columns.Clear();
            if (View != null)
            {
                foreach (DataColumn column in View.Table.Columns)
                {
                    var c = CreateColumn (column);
                    Columns.Add (c);
                }
            }
        }

        #endregion

        #region Protected Methods

        /// <inheritdoc/>
        protected override object GetValue (Column column)
        {
            if (column == null)
            {
                return null;
            }

            if (column.Tag == null)
            {
                column.Tag = View.Table.Columns.IndexOf (column.Name);
            }

            return CurrentRow == null ? null : ((DataRowView)CurrentRow)[(int)column.Tag];
        }

        #endregion

        #region Public Methods

        /// <inheritdoc/>
        public override void InitSchema()
        {
            if (Columns.Count == 0)
            {
                CreateColumns();
            }

            foreach (Column column in Columns)
            {
                column.Tag = null;
            }
        }

        /// <inheritdoc/>
        public override void LoadData (IList rows)
        {
            // custom load data via Load event
            OnLoad();

            var needReload = ForceLoadData || rows.Count == 0;
            if (needReload)
            {
                // fill rows
                rows.Clear();
                for (var i = 0; i < View.Count; i++)
                {
                    rows.Add (View[i]);
                }
            }
        }

        internal void RefreshColumns()
        {
            if (View != null)
            {
                // add new columns
                foreach (DataColumn column in View.Table.Columns)
                {
                    if (Columns.FindByName (column.ColumnName) == null)
                    {
                        var c = CreateColumn (column);
                        c.Enabled = true;
                        Columns.Add (c);
                    }
                }

                // delete obsolete columns
                var i = 0;
                while (i < Columns.Count)
                {
                    var c = Columns[i];
                    if (!c.Calculated && !View.Table.Columns.Contains (c.Name))
                    {
                        c.Dispose();
                    }
                    else
                    {
                        i++;
                    }
                }
            }
        }

        #endregion
    }
}
